package com.link2room.rodimus.facade.impl;

import com.link2room.aeriabots.dto.param.inside.WxPromotionTransfersInsideParamDto;
import com.link2room.aeriabots.dto.param.inside.WxQrcodeInsideParamDto;
import com.link2room.aeriabots.dto.result.base.WxPromotionTransfersResDto;
import com.link2room.aeriabots.dto.result.base.WxQrcodeResDto;
import com.link2room.common.constant.DefaultValue;
import com.link2room.common.dto.param.base.BaseL2rParamDto;
import com.link2room.common.dto.param.base.BaseParamDto;
import com.link2room.common.dto.threadlocal.BaseThreadLocal;
import com.link2room.common.entity.BaseEntity;
import com.link2room.common.exception.SysException;
import com.link2room.common.jpa.condition.ConditionDetail;
import com.link2room.common.jpa.condition.L2RCondition;
import com.link2room.common.jpa.criteria.CriteriaUtil;
import com.link2room.common.jpa.result.QueryResult;
import com.link2room.common.mns.MNSUtil;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.*;
import com.link2room.enums.exception.RodimusSysExceptionEnum;
import com.link2room.perceptor.dto.result.BatchInfoDelayedDto;
import com.link2room.rodimus.constant.InComingDetailConstant;
import com.link2room.rodimus.constant.RodimusMnsConstant;
import com.link2room.rodimus.constant.RodimusTaskNameConstant;
import com.link2room.rodimus.constant.SaleMemberConstant;
import com.link2room.rodimus.dto.param.inside.SalesmanInComeDetailInsideParamDto;
import com.link2room.rodimus.dto.param.manager.SalesmanLeadingParamDto;
import com.link2room.rodimus.dto.param.manager.SalesmanManagerParamDto;
import com.link2room.rodimus.dto.result.base.SalesmanBaseDto;
import com.link2room.rodimus.dto.result.base.SalesmanIncomeDetailDto;
import com.link2room.rodimus.dto.result.base.SalesmanMemberDto;
import com.link2room.rodimus.dto.result.manager.IncomdetailSchedulesDto;
import com.link2room.rodimus.entity.*;
import com.link2room.rodimus.exception.IncomeDetailException;

import com.link2room.rodimus.facade.ISalesmaManagerFacadeService;
import com.link2room.rodimus.feign.aeriabots.WxPromotionTransfersFeignService;
import com.link2room.rodimus.feign.aeriabots.WxQrcodeFeignService;
import com.link2room.rodimus.feign.perceptor.BatchInfoFeignService;
import com.link2room.rodimus.feign.soundwave.PmsReservationFeignService;
import com.link2room.rodimus.service.ISalesmanRewardsService;
import com.link2room.rodimus.service.ISalesmanService;
import com.link2room.rodimus.service.ISchedulesService;
import com.link2room.sideswipe.sideswipe.dto.base.OrganizationDto;
import com.link2room.sideswipe.sideswipe.dto.param.FindOrganizationByCodeParamDto;
import com.link2room.sideswipe.sideswipeClient.sdk.ISideswipeClientAPIService;
import com.link2room.soundwave.dto.param.inside.BookInfoListInsideParamDto;
import com.link2room.soundwave.dto.result.base.PmsBookInfoDto;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import static com.link2room.enums.exception.RodimusSysExceptionEnum.SALESMAN_NOT_EXIT;
import static com.link2room.enums.exception.RodimusSysExceptionEnum.SALESMAN_SOURCE_LEADIN_ERROR;


/**
 * Created by VegetaKo on 2016/10/11.
 */
@Service("salesmanManagerFacadeService")
public class SalesmaManagerFacadeServiceImpl implements ISalesmaManagerFacadeService {

    @Resource
    private ICommonService commonService;

    @Autowired
    private WxQrcodeFeignService wxQrcodeFeignService;

    @Resource
    private ISalesmanRewardsService salesmanRewardsService;

    @Autowired
    private PmsReservationFeignService pmsReservationFeignService;

    @Resource
    private ISchedulesService schedulesService;

    @Autowired
    private BatchInfoFeignService batchInfoFeignService;

    @Resource
    private ISideswipeClientAPIService sideswipeClientAPIService;

    @Autowired
    private WxPromotionTransfersFeignService wxPromotionTransfersFeignService;


    @Resource
    private MNSUtil mnsUtil;

    @Resource
    private ISalesmanService salesmanService;

    @Override
    public SalesmanBaseDto getSalesmanBySalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        SalesmanBase salesmanBase = new SalesmanBase();
        salesmanBase.setSalesmanNo(salesmanManagerParamDto.getSalesmanNo());
        salesmanBase.setId(salesmanManagerParamDto.getId());
        salesmanBase = commonService.findOneEQ(SalesmanBase.class, salesmanBase);
        L2RAssert.isTrue(null == salesmanBase, new SysException(SALESMAN_NOT_EXIT));
        SalesmanBaseDto salesmanBaseDto = ClassConverUtil.copyPropertiesToDto(salesmanBase, SalesmanBaseDto.class, true);
        if (StringUtil.isNotBlank(salesmanBaseDto.getOrganizationCode())) {
            FindOrganizationByCodeParamDto paramDto = new FindOrganizationByCodeParamDto();
            paramDto.setCode(salesmanBaseDto.getOrganizationCode());
            OrganizationDto qres = sideswipeClientAPIService.findOrganizationByCode(paramDto);
            if (qres != null) {
                salesmanBaseDto.setOrganizationName(qres.getName());
            }
        }
        return salesmanBaseDto;
    }

    @Override
    public void auditSalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        SalesmanBase salesmanBase = new SalesmanBase();
        salesmanBase.setSalesmanNo(salesmanManagerParamDto.getSalesmanNo());
        salesmanBase = commonService.findOneEQ(SalesmanBase.class, salesmanBase);
        L2RAssert.isTrue(salesmanBase == null, new SysException(SALESMAN_NOT_EXIT, "分销员不存在."));
        if (SaleMemberConstant.STA.I.equals(salesmanManagerParamDto.getSta())) {
            if (StringUtil.isBlank(salesmanBase.getQrCode())) {

                List params = new ArrayList<>();
                params.add("SALESMAN");
                String newSalesmanNo = commonService.findOneFieldByProcedure("create_No", params);

                WxQrcodeInsideParamDto wxQrcodeInsideParamDto = new WxQrcodeInsideParamDto();
                wxQrcodeInsideParamDto.setType("Salesman");
                wxQrcodeInsideParamDto.setKey(newSalesmanNo);
                WxQrcodeResDto wxQrcodeResDto = wxQrcodeFeignService.createWxQrCode(wxQrcodeInsideParamDto).getResultInfo();
                if (null == wxQrcodeResDto.getTicket()) {
                    throw new SysException(RodimusSysExceptionEnum.SALES_MAN_QRCODE_NOT_EXIT);
                }
                salesmanBase.setQrCode(wxQrcodeResDto.getTicket());
                salesmanBase.setSalesmanNo(newSalesmanNo);
            }
        }
        salesmanBase.setSta(salesmanManagerParamDto.getSta());
        commonService.merge(salesmanBase);
    }

    @Override
    public void modifySalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        String organizationCode = salesmanManagerParamDto.getOrganizationCode();
        L2RAssert.stringBlank(organizationCode, "[organizationCode] is null.");
        String salesmanName = salesmanManagerParamDto.getSalesmanName();
        L2RAssert.stringBlank(salesmanName, "[salesmanName] is null.");
        String mobile = salesmanManagerParamDto.getMobile();
        L2RAssert.stringBlank(mobile, "[mobile] is null.");
        SalesmanBase salesmanBase = new SalesmanBase();
        salesmanBase.setSalesmanNo(salesmanManagerParamDto.getSalesmanNo());
        salesmanBase = commonService.findOneEQ(SalesmanBase.class, salesmanBase);
        salesmanBase.setSalesmanName(salesmanName);
        salesmanBase.setLhotelCode(organizationCode);
        salesmanBase.setOrganizationCode(organizationCode);
        salesmanBase.setMobile(mobile);
        commonService.merge(salesmanBase);
    }

    @Override
    public void disableSalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        SalesmanBase salesmanBase = new SalesmanBase();
        salesmanBase.setId(salesmanManagerParamDto.getId());
        salesmanBase.setSalesmanNo(salesmanManagerParamDto.getSalesmanNo());
        salesmanBase = commonService.findOneEQ(SalesmanBase.class, salesmanBase);
        salesmanBase.setSta("X");
        commonService.merge(salesmanBase);
    }

    @Override
    public void auditSalesmanIncomeDetail() throws Exception {
        String lhotelGorupCode = new BaseParamDto().getLhotelGroupCode();
        L2RAssert.stringBlank(lhotelGorupCode, "[lhotelGorupCode] is null");
        SalesmanIncomeDetail salesmans = new SalesmanIncomeDetail();
        salesmans.setLhotelGroupCode(lhotelGorupCode);
        salesmans.setAwardSta(InComingDetailConstant.AwardSta.CHECKED);
        QueryResult<SalesmanIncomeDetail> sms = commonService.findAllEQ(SalesmanIncomeDetail.class, salesmans, 0, Integer.MAX_VALUE, null, new String[]{SalesmanIncomeDetail.SalesmanIncomeDetail_.salesmanNo.toString()});
        if (null != sms && sms.getResultlist().size() > 0) {
            for (SalesmanIncomeDetail sid : sms.getResultlist()) {
                String sn = sid.getSalesmanNo();
                //会员奖励
                SalesmanIncomeDetail member = new SalesmanIncomeDetail();
                member.setAwardSta(InComingDetailConstant.AwardSta.CHECKED);
                member.setAwardType(InComingDetailConstant.AwardType.MEMBER);
                member.setSalesmanNo(sn);
                member.setLhotelGroupCode(lhotelGorupCode);
                QueryResult<SalesmanIncomeDetail> members = new QueryResult<>();
                members = commonService.findAllEQ(SalesmanIncomeDetail.class, member);
                if (null != members && members.getResultlist().size() > 0) {
                    List params = new ArrayList<>();
                    params.add("AWARDPAYNO");
                    String l2rPayNo = commonService.findOneFieldByProcedure("create_No", params);

                    BigDecimal memberTotal = BigDecimal.ZERO;
                    SalesmanPayment memberPayment = new SalesmanPayment();
                    memberPayment.setLhotelGroupCode(sid.getLhotelGroupCode());
                    memberPayment.setLhotelCode(sid.getLhotelCode());
                    memberPayment.setSalesmanNo(sid.getSalesmanNo());
                    memberPayment.setSalesmanName(sid.getSalesmanName());
                    memberPayment.setL2RPayNo(l2rPayNo);
                    memberPayment.setPayType(member.getAwardType());
                    memberPayment.setPaySta(InComingDetailConstant.PaySta.INIT);
                    memberPayment.setAuditedDate(new Date());

                    for (SalesmanIncomeDetail s : members.getResultlist()) {
                        memberTotal = memberTotal.add(s.getTotal());
                    }
                    if (memberTotal.compareTo(BigDecimal.ONE) >= 0) {
                        for (SalesmanIncomeDetail s : members.getResultlist()) {
                            s.setL2RPayNo(l2rPayNo);
                            s.setAwardSta(InComingDetailConstant.AwardSta.AUDITED);

                        }
                        commonService.mergeList(members.getResultlist());
                        memberPayment.setTotal(memberTotal);
                        commonService.save(memberPayment);
                    }

                }

                //订单奖励
                SalesmanIncomeDetail reservation = new SalesmanIncomeDetail();
                reservation.setAwardSta(InComingDetailConstant.AwardSta.CHECKED);
                reservation.setAwardType(InComingDetailConstant.AwardType.RESERVATION);
                reservation.setSalesmanNo(sn);
                QueryResult<SalesmanIncomeDetail> reservations = new QueryResult<>();
                reservations = commonService.findAllEQ(SalesmanIncomeDetail.class, reservation);
                if (null != reservations && reservations.getResultlist().size() > 0) {
                    List params = new ArrayList<>();
                    params.add("AWARDPAYNO");
                    String l2rPayNo = commonService.findOneFieldByProcedure("create_No", params);

                    BigDecimal reservationTotal = BigDecimal.ZERO;
                    SalesmanPayment reservationPayment = new SalesmanPayment();
                    reservationPayment.setLhotelGroupCode(sid.getLhotelGroupCode());
                    reservationPayment.setLhotelCode(sid.getLhotelCode());
                    reservationPayment.setSalesmanNo(sid.getSalesmanNo());
                    reservationPayment.setSalesmanName(sid.getSalesmanName());
                    reservationPayment.setL2RPayNo(l2rPayNo);
                    reservationPayment.setPayType(reservation.getAwardType());
                    reservationPayment.setPaySta(InComingDetailConstant.PaySta.INIT);
                    reservationPayment.setAuditedDate(new Date());

                    for (SalesmanIncomeDetail s : reservations.getResultlist()) {
                        reservationTotal = reservationTotal.add(s.getTotal());
                    }
                    if (reservationTotal.compareTo(BigDecimal.ONE) >= 0) {
                        for (SalesmanIncomeDetail s : reservations.getResultlist()) {
                            s.setL2RPayNo(l2rPayNo);
                            s.setAwardSta(InComingDetailConstant.AwardSta.AUDITED);
                        }
                        commonService.mergeList(reservations.getResultlist());
                        reservationPayment.setTotal(reservationTotal);
                        commonService.save(reservationPayment);
                    }
                }
            }
        }

        commonService.excuteByNative("rankinglist", null);
    }

    @Override
    public void startPaySalesmanIncomeDetail() throws Exception {
        String taskMainId = startSalemanIncomingTransfer();
        if (StringUtil.isNotBlank(taskMainId)) {
            schedulesService.setIncomedetailScheduleOptid(BaseThreadLocal.getLhotelGroupCode(), taskMainId);
        }
    }

    @Override
    public void paySalesmanAwardMemberStep(SalesmanInComeDetailInsideParamDto paramDto) throws Exception {
        if (InComingDetailConstant.AwardType.MEMBER.equals(paramDto.getAwardType())) {
            try {
                _PayTaskRes res = doAward(paramDto.getLhotelGroupCode(), paramDto.getSalesmanNo(), InComingDetailConstant.AwardType.MEMBER, paramDto.getSpBillCreateIP());
                if (!res.isSusscee()) {
                    LogUtil.logger.warn("奖励方法错误:异常单号:" + "failPayNo:" + res.getFailPayNos());
                    throw new IncomeDetailException(RodimusSysExceptionEnum.AWARD_ERROR, res.getFailPayNos());
                }
            } finally {
                //put msg RESERVATION
                delayStartReservationAward(paramDto);
            }
        }
    }

    @Override
    public void paySalesmanAwardReservationStep(SalesmanInComeDetailInsideParamDto paramDto) throws Exception {
        if (InComingDetailConstant.AwardType.RESERVATION.equals(paramDto.getAwardType())) {
            _PayTaskRes res;
            res = doAward(paramDto.getLhotelGroupCode(), paramDto.getSalesmanNo(), InComingDetailConstant.AwardType.RESERVATION, paramDto.getSpBillCreateIP());
            if (!res.isSusscee()) {
                LogUtil.logger.warn("奖励方法错误:异常单号:" + "failPayNo:" + res.getFailPayNos());
                throw new IncomeDetailException(RodimusSysExceptionEnum.AWARD_ERROR, res.getFailPayNos());
            } else {
                // complate batch task
                BatchUtil.doBatchTaskDone(paramDto.getTaskMainId(), paramDto.getTaskId(), paramDto.getIsBatch());
            }
        }
    }

    /**
     * 发送15秒延迟消息,订单奖励任务
     *
     * @param paramDto
     */
    private void delayStartReservationAward(SalesmanInComeDetailInsideParamDto paramDto) {
        if (paramDto == null) {
            return;
        }
        paramDto.setAwardType(InComingDetailConstant.AwardType.RESERVATION);
        int delaySecond = 15;
        mnsUtil.putDelayMessageToQueue(RodimusMnsConstant.QUEUE_SALEMAN_INCOME_TRANSFER_RESERVATION, JacksonUtil.beanToJson(paramDto), delaySecond);
    }

    @Override
    public QueryResult<SalesmanBaseDto> listSalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        L2RCondition l2RCondition = new L2RCondition();
        ArrayList<ConditionDetail> conditionDetailArrayList = new ArrayList<>();
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.GTE, salesmanManagerParamDto.getStartDatetime()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.LTE, salesmanManagerParamDto.getEndDatetime()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.lhotelCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelCode()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelGroupCode()));
        if (StringUtil.isNotBlank(salesmanManagerParamDto.getSalesmanName())) {
            conditionDetailArrayList.add(new ConditionDetail(SalesmanBase.SalesmanBase_.salesmanName.toString(), CriteriaUtil.Operator.LIKE, salesmanManagerParamDto.getSalesmanName() + "%"));
        }
        conditionDetailArrayList.add(new ConditionDetail(SalesmanBase.SalesmanBase_.sta.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getSta()));
        ConditionDetail[] conditionDetails = new ConditionDetail[conditionDetailArrayList.size()];
        for (int i = 0; i < conditionDetailArrayList.size(); i++) {
            conditionDetails[i] = conditionDetailArrayList.get(i);
        }
        l2RCondition.setAndConditions(conditionDetails);
        QueryResult<SalesmanBase> salesmanBaseQueryResult = commonService.findAllByCondition(SalesmanBase.class, l2RCondition, salesmanManagerParamDto.getCurrentPage(), salesmanManagerParamDto.getPageSize());
        QueryResult<SalesmanBaseDto> salesmanBaseManagerDtoQueryResult;
        salesmanBaseManagerDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(salesmanBaseQueryResult, SalesmanBaseDto.class, true);

        return salesmanBaseManagerDtoQueryResult;
    }


    @Override
    public QueryResult<SalesmanIncomeDetailDto> listSalesmanIncomeDetail(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {

        L2RCondition l2RCondition = new L2RCondition();
        ArrayList<ConditionDetail> conditionDetailArrayList = new ArrayList<>();
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.GTE, salesmanManagerParamDto.getStartDate()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.LTE, salesmanManagerParamDto.getEndDate()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.lhotelCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelCode()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelGroupCode()));
        conditionDetailArrayList.add(new ConditionDetail(SalesmanIncomeDetail.SalesmanIncomeDetail_.salesmanNo.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getSalesmanNo()));
        conditionDetailArrayList.add(new ConditionDetail(SalesmanIncomeDetail.SalesmanIncomeDetail_.awardSta.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getAwardSta()));
        ConditionDetail[] conditionDetails = new ConditionDetail[conditionDetailArrayList.size()];
        for (int i = 0; i < conditionDetailArrayList.size(); i++) {
            conditionDetails[i] = conditionDetailArrayList.get(i);
        }
        l2RCondition.setAndConditions(conditionDetails);

        QueryResult<SalesmanIncomeDetail> salesmanIncomeDetailQueryResult = commonService.findAllByCondition(SalesmanIncomeDetail.class, l2RCondition, salesmanManagerParamDto.getCurrentPage(), salesmanManagerParamDto.getPageSize());

        QueryResult<SalesmanIncomeDetailDto> salesmanIncomeDetailDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(salesmanIncomeDetailQueryResult, SalesmanIncomeDetailDto.class, true);
        BookInfoListInsideParamDto bookInfoListInsideParamDto = new BookInfoListInsideParamDto();
        bookInfoListInsideParamDto.setLhotelGroupCode(salesmanManagerParamDto.getLhotelGroupCode());
        bookInfoListInsideParamDto.setL2rNos("");
        for (SalesmanIncomeDetailDto salesmanIncomeDetailDto : salesmanIncomeDetailDtoQueryResult.getResultlist()) {
            if (salesmanIncomeDetailDto.getAwardType().equals("RESERVATION")) {
                bookInfoListInsideParamDto.setL2rNos(bookInfoListInsideParamDto.getL2rNos() + "," + salesmanIncomeDetailDto.getL2RNo());
            }


        }
        if (null != bookInfoListInsideParamDto.getL2rNos() && bookInfoListInsideParamDto.getL2rNos().length() > 0) {
            QueryResult<PmsBookInfoDto> pmsBookInfoDtoQueryResult = pmsReservationFeignService.getPMSReservations(bookInfoListInsideParamDto.paramToMap()).getQueryResult();
            HashMap<String, String> l2RCrsNo = new HashMap<>();
            for (PmsBookInfoDto pmsBookInfoDto : pmsBookInfoDtoQueryResult.getResultlist()) {
                l2RCrsNo.put(pmsBookInfoDto.getL2RNo(), pmsBookInfoDto.getCrsNo());
            }
            for (SalesmanIncomeDetailDto salesmanIncomeDetailDto : salesmanIncomeDetailDtoQueryResult.getResultlist()) {
                if (salesmanIncomeDetailDto.getAwardType().equals("RESERVATION")) {
                    salesmanIncomeDetailDto.setCrsNo(l2RCrsNo.get(salesmanIncomeDetailDto.getL2RNo()));
                }
            }
        }

        return salesmanIncomeDetailDtoQueryResult;
    }

    @Override
    public QueryResult<SalesmanIncomeDetailDto> listSalesmanIncomeDetailBySalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        L2RCondition l2RCondition = new L2RCondition();
        l2RCondition.setAndConditions(new ConditionDetail[]{new ConditionDetail(SalesmanIncomeDetail.SalesmanIncomeDetail_.salesmanNo.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getSalesmanNo())});
        QueryResult<SalesmanIncomeDetail> salesmanIncomeDetailQueryResult = commonService.findAllByCondition(SalesmanIncomeDetail.class, l2RCondition, salesmanManagerParamDto.getCurrentPage(), salesmanManagerParamDto.getPageSize());
        QueryResult<SalesmanIncomeDetailDto> salesmanIncomeDetailManagerDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(salesmanIncomeDetailQueryResult, SalesmanIncomeDetailDto.class, true);

        BookInfoListInsideParamDto bookInfoListInsideParamDto = new BookInfoListInsideParamDto();
        bookInfoListInsideParamDto.setLhotelGroupCode(salesmanManagerParamDto.getLhotelGroupCode());
        bookInfoListInsideParamDto.setL2rNos("");
        for (SalesmanIncomeDetailDto salesmanIncomeDetailDto : salesmanIncomeDetailManagerDtoQueryResult.getResultlist()) {
            if (salesmanIncomeDetailDto.getAwardType().equals("RESERVATION")) {
                bookInfoListInsideParamDto.setL2rNos(bookInfoListInsideParamDto.getL2rNos() + "," + salesmanIncomeDetailDto.getL2RNo());
            }


        }
        if (null != bookInfoListInsideParamDto.getL2rNos() && bookInfoListInsideParamDto.getL2rNos().length() > 0) {
            QueryResult<PmsBookInfoDto> pmsBookInfoDtoQueryResult = pmsReservationFeignService.getPMSReservations(bookInfoListInsideParamDto.paramToMap()).getQueryResult();
            HashMap<String, String> l2RCrsNo = new HashMap<>();
            for (PmsBookInfoDto pmsBookInfoDto : pmsBookInfoDtoQueryResult.getResultlist()) {
                l2RCrsNo.put(pmsBookInfoDto.getL2RNo(), pmsBookInfoDto.getCrsNo());
            }
            for (SalesmanIncomeDetailDto salesmanIncomeDetailDto : salesmanIncomeDetailManagerDtoQueryResult.getResultlist()) {
                if (salesmanIncomeDetailDto.getAwardType().equals("RESERVATION")) {
                    salesmanIncomeDetailDto.setCrsNo(l2RCrsNo.get(salesmanIncomeDetailDto.getL2RNo()));
                }
            }
        }

        return salesmanIncomeDetailManagerDtoQueryResult;
    }

    @Override
    public QueryResult<SalesmanMemberDto> listSalesmanMember(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        L2RCondition l2RCondition = new L2RCondition();
        ArrayList<ConditionDetail> conditionDetailArrayList = new ArrayList<>();
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.GTE, salesmanManagerParamDto.getStartDatetime()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.createDatetime.toString(), CriteriaUtil.Operator.LTE, salesmanManagerParamDto.getEndDatetime()));
        conditionDetailArrayList.add(new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelGroupCode()));

        ConditionDetail[] conditionDetails = new ConditionDetail[conditionDetailArrayList.size()];
        for (int i = 0; i < conditionDetailArrayList.size(); i++) {
            conditionDetails[i] = conditionDetailArrayList.get(i);
        }
        l2RCondition.setAndConditions(conditionDetails);
        QueryResult<SalesmanMember> salesmanMemberQueryResult = commonService.findAllByCondition(SalesmanMember.class, l2RCondition, salesmanManagerParamDto.getCurrentPage(), salesmanManagerParamDto.getPageSize());

        QueryResult<SalesmanMemberDto> salesmanMemberManagerDtoQueryResult = ClassConverUtil.copyQueryResultToDtoQueryResult(salesmanMemberQueryResult, SalesmanMemberDto.class, true);

        return salesmanMemberManagerDtoQueryResult;
    }

    @Override
    public QueryResult<SalesmanMemberDto> listSalesmanMemberBySalesman(SalesmanManagerParamDto salesmanManagerParamDto) throws Exception {
        String salesmanNo = salesmanManagerParamDto.getSalesmanNo();
        L2RAssert.stringBlank(salesmanNo, "[salesmanNo] is null.");
        L2RCondition l2RCondition = new L2RCondition();
        l2RCondition.setAndConditions(
                new ConditionDetail[]{
                        new ConditionDetail(SalesmanMember.SalesmanMember_.salesmanNo.toString(), CriteriaUtil.Operator.EQ, salesmanNo),
                        new ConditionDetail(SalesmanMember.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ, salesmanManagerParamDto.getLhotelGroupCode())
                });
        QueryResult<SalesmanMember> salesmanMemberQueryResult = commonService.findAllByCondition(SalesmanMember.class, l2RCondition, salesmanManagerParamDto.getCurrentPage(), salesmanManagerParamDto.getPageSize());
        return ClassConverUtil.copyQueryResultToDtoQueryResult(salesmanMemberQueryResult, SalesmanMemberDto.class, true);
    }

    @Override
    public IncomdetailSchedulesDto incomdetailSchedules(BaseParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        L2RAssert.stringBlank(lhotelGroupCode, "[lhotelGroupCode] is null");
        IncomdetailSchedulesDto resDto = new IncomdetailSchedulesDto();
        String taskMainId = schedulesService.getIncomedetailScheduleOptid(lhotelGroupCode);
        if (StringUtil.isBlank(taskMainId)) {
            resDto.setIsWorking(DefaultValue.F);
        } else {
            BaseL2rParamDto batchDto = new BaseL2rParamDto();
            batchDto.setLhotelGroupCode(lhotelGroupCode);
            batchDto.setTaskMainId(taskMainId);
            BatchInfoDelayedDto delayedDto = batchInfoFeignService.getBatchInfos(batchDto.paramToMap()).getResultInfo();
            resDto.setDelayedDto(delayedDto);
            if (delayedDto.getTaskPercent() < 100) {
                resDto.setIsWorking(DefaultValue.T);
            } else {
                resDto.setIsWorking(DefaultValue.F);
            }
        }
        return resDto;
    }

    @Override
    public void salesmanLeading(SalesmanLeadingParamDto paramDto) throws Exception {
        String lhotelGroupCode = paramDto.getLhotelGroupCode();
        SalesmanSourceDataEntity findSource = new SalesmanSourceDataEntity();
        findSource.setLhotelGroupCode(lhotelGroupCode);
        findSource.setIsLeadin(DefaultValue.F);
        QueryResult<SalesmanSourceDataEntity> qres = commonService.findAllEQ(SalesmanSourceDataEntity.class, findSource);
        L2RAssert.isTrue(CollectionUtils.isEmpty(qres.getResultlist()), new SysException(SALESMAN_SOURCE_LEADIN_ERROR, "没有导入数据.[lhotelGroupCode] is " + lhotelGroupCode));
        //是否导入
        List<String> mobiles = qres.getResultlist().stream()
                .map(SalesmanSourceDataEntity::getMobile)
                .collect(Collectors.toList());
        L2RCondition condition = new L2RCondition();
        condition.setAndConditions(new ConditionDetail[]{
                new ConditionDetail(BaseEntity.BaseEntity_.lhotelGroupCode.toString(), CriteriaUtil.Operator.EQ,lhotelGroupCode),
                new ConditionDetail(SalesmanBase.SalesmanBase_.mobile.toString(), CriteriaUtil.Operator.IN,mobiles)
        });
        QueryResult<SalesmanBase> hasLead = commonService.findAllByCondition(SalesmanBase.class, condition);
        L2RAssert.isTrue(CollectionUtils.isNotEmpty(hasLead.getResultlist()),new SysException(SALESMAN_SOURCE_LEADIN_ERROR,"手机号与现分销员手机号重复[mobiles]"+hasLead.getResultlist().stream().map(SalesmanBase::getMobile).collect(Collectors.toList())));
        List<SalesmanMappingEntity> salesmanMappingEntityList = new ArrayList<>();
        List<SalesmanBase> salesmans = qres.getResultlist().stream()
                .map(sourceDate -> {
                    List params = new ArrayList<>();
                    params.add("SALESMAN");
                    String newSalesmanNo = null;
                    try {
                        newSalesmanNo = commonService.findOneFieldByProcedure("create_No", params);
                    } catch (Exception e) {
                        throw new SysException(SALESMAN_SOURCE_LEADIN_ERROR, "分销员码生成错误.");
                    }

                    WxQrcodeInsideParamDto wxQrcodeInsideParamDto = new WxQrcodeInsideParamDto();
                    wxQrcodeInsideParamDto.setType("Salesman");
                    wxQrcodeInsideParamDto.setKey(newSalesmanNo);
                    WxQrcodeResDto wxQrcodeResDto = null;
                    try {
                        wxQrcodeResDto = wxQrcodeFeignService.createWxQrCode(wxQrcodeInsideParamDto).getResultInfo();
                    } catch (Exception e) {
                        throw new SysException(SALESMAN_SOURCE_LEADIN_ERROR, "分销员二维码获得错误.");
                    }
                    if (null == wxQrcodeResDto.getTicket()) {
                        throw new SysException(RodimusSysExceptionEnum.SALES_MAN_QRCODE_NOT_EXIT);
                    }
                    //映射
                    SalesmanMappingEntity salesmanMappingEntity = new SalesmanMappingEntity();
                    salesmanMappingEntity.setEmployeeNo(sourceDate.getEmployeeNo());
                    salesmanMappingEntity.setSalesmanNo(newSalesmanNo);
                    salesmanMappingEntity.setLhotelGroupCode(lhotelGroupCode);
                    salesmanMappingEntity.setLhotelCode(sourceDate.getLhotelCode());
                    salesmanMappingEntityList.add(salesmanMappingEntity);
                    //生成分销员
                    SalesmanBase newSalesman = new SalesmanBase();
                    newSalesman.setLhotelGroupCode(lhotelGroupCode);
                    newSalesman.setMobile(sourceDate.getMobile());
                    newSalesman.setSalesmanNo(newSalesmanNo);
                    newSalesman.setSta(SaleMemberConstant.STA.I);
                    newSalesman.setOrganizationCode(sourceDate.getOrganizationCode());
                    newSalesman.setRewards(BigDecimal.ZERO);
                    newSalesman.setQrCode(wxQrcodeResDto.getTicket());
                    newSalesman.setMembers(BigDecimal.ZERO);
                    newSalesman.setNights(BigDecimal.ZERO);
                    newSalesman.setLhotelCode(sourceDate.getLhotelCode());
                    newSalesman.setSalesmanName(sourceDate.getName());
                    newSalesman.setIsHalt(DefaultValue.F);
                    return newSalesman;
                })
                .collect(Collectors.toList());
        salesmanService.salesmanLeadin(salesmans,salesmanMappingEntityList);
        qres.getResultlist().stream().forEach(date->date.setIsLeadin(DefaultValue.T));
        commonService.saveOrMergeList(qres.getResultlist());
    }

    /**
     * 微信企业支付 发放分销员奖励
     *
     * @param lhotelGroupCode
     * @param salesmanNo
     * @param awardType
     * @param spBillCreateIP
     * @throws Exception
     */
    private _PayTaskRes doAward(String lhotelGroupCode, String salesmanNo, String awardType, String spBillCreateIP) throws Exception {
        boolean success = true;
        _PayTaskRes payTaskRes = new _PayTaskRes(success);
        SalesmanPayment salesmanPaymentMember = new SalesmanPayment();
        salesmanPaymentMember.setPaySta(InComingDetailConstant.PaySta.INIT);
        salesmanPaymentMember.setLhotelGroupCode(lhotelGroupCode);
        salesmanPaymentMember.setSalesmanNo(salesmanNo);
        salesmanPaymentMember.setPayType(awardType);
        QueryResult<SalesmanPayment> salesmanPaymentQueryResult = commonService.findAllEQ(SalesmanPayment.class, salesmanPaymentMember);
        if (null != salesmanPaymentQueryResult && salesmanPaymentQueryResult.getResultlist().size() > 0) {
            for (SalesmanPayment sp : salesmanPaymentQueryResult.getResultlist()) {
                SalesmanBase salesmanBase = new SalesmanBase();
                salesmanBase.setSalesmanNo(sp.getSalesmanNo());
                salesmanBase = commonService.findOneEQ(SalesmanBase.class, salesmanBase);
                WxPromotionTransfersInsideParamDto wxPromotionTransfersInsideParamDto = new WxPromotionTransfersInsideParamDto();
                wxPromotionTransfersInsideParamDto.setAmount(sp.getTotal());
                wxPromotionTransfersInsideParamDto.setDesc(sp.getSalesmanName() + sp.getPayType());
                wxPromotionTransfersInsideParamDto.setOpenid(salesmanBase.getSalesmanWxopenid());
                wxPromotionTransfersInsideParamDto.setPartnerTradeNo(sp.getL2RPayNo());
                wxPromotionTransfersInsideParamDto.setReUserName(salesmanBase.getSalesmanName());
                wxPromotionTransfersInsideParamDto.setSpBillCreateIP(spBillCreateIP);
                WxPromotionTransfersResDto wxPromotionTransfersResDto = null;
                try {
                    wxPromotionTransfersResDto = wxPromotionTransfersFeignService.promotionTransfers(wxPromotionTransfersInsideParamDto).getResultInfo();
                } catch (Exception e) {
                    //奖励发放异常 记录单号
                    payTaskRes.setSusscee(false);
                    payTaskRes.setFailPayNos(payTaskRes.getFailPayNos() + " " + sp.getL2RPayNo());
                    continue;
                }
                sp.setPaymentNo(wxPromotionTransfersResDto.getPaymentNo());
                sp.setPaySta(InComingDetailConstant.PaySta.PAID);
                SalesmanIncomeDetail salesmanIncomeDetail = new SalesmanIncomeDetail();
                salesmanIncomeDetail.setL2RPayNo(sp.getL2RPayNo());
                QueryResult<SalesmanIncomeDetail> salesmanIncomeDetailQueryResult = commonService.findAllEQ(SalesmanIncomeDetail.class, salesmanIncomeDetail);
                for (SalesmanIncomeDetail sid : salesmanIncomeDetailQueryResult.getResultlist()) {
                    sid.setAwardSta(InComingDetailConstant.AwardSta.PAID);
                }
                salesmanBase.setRewards(salesmanBase.getRewards().add(sp.getTotal()));
                salesmanRewardsService.updateSalesmanRewardsPayments(salesmanBase, salesmanIncomeDetailQueryResult.getResultlist(), sp);
            }
        }
        return payTaskRes;
    }

    private static class _PayTaskRes {
        public _PayTaskRes() {
        }

        public _PayTaskRes(boolean susscee) {
            this.susscee = susscee;
            this.failPayNos = "";
        }

        private boolean susscee;
        private String failPayNos;

        public boolean isSusscee() {
            return susscee;
        }

        public void setSusscee(boolean susscee) {
            this.susscee = susscee;
        }

        public String getFailPayNos() {
            return failPayNos;
        }

        public void setFailPayNos(String failPayNos) {
            this.failPayNos = failPayNos;
        }
    }

    /**
     * 分销员奖励发放任务启动启动
     */
    private String startSalemanIncomingTransfer() throws Exception {
        List<String> salesmanNos = this.selectNeedToPaySalesman();
        if (salesmanNos == null) {
            return null;
        }
        List<SalesmanInComeDetailInsideParamDto> salesmanInComeDetailInsideParamDtos = new ArrayList<>();
        salesmanNos.stream().forEach(salesmanNo ->
                salesmanInComeDetailInsideParamDtos.add(new SalesmanInComeDetailInsideParamDto(salesmanNo, InComingDetailConstant.AwardType.MEMBER))
        );
        return BatchUtil.beginBatchTask(RodimusMnsConstant.QUEUE_SALEMAN_INCOME_TRANSFER,
                RodimusTaskNameConstant.SALES_MAN_INCOME,
                salesmanInComeDetailInsideParamDtos);
    }


    /**
     * 发放组织列表查询
     * TODO 暂时根据 SalesmanPayment 表来group by ，考虑到此表越来越大，后需要定出 系统 角色组织架构，从此架构表中拉出列表
     *
     * @return
     * @throws Exception
     */
    private List<String> selectNeedToPaySalesman() throws Exception {
        SalesmanPayment findSalesmans = new SalesmanPayment();
        findSalesmans.setLhotelGroupCode(new BaseParamDto().getLhotelGroupCode());
        findSalesmans.setPaySta(InComingDetailConstant.PaySta.INIT);
        QueryResult<SalesmanPayment> queryRes = commonService.findAllEQ(
                SalesmanPayment.class,
                findSalesmans,
                0,
                Integer.MAX_VALUE,
                null,
                new String[]{SalesmanIncomeDetail.SalesmanIncomeDetail_.salesmanNo.toString()});
        if (queryRes == null || queryRes.getResultlist() == null || queryRes.getResultlist().size() == 0) {
            return null;
        }
        return queryRes.getResultlist().stream().map(SalesmanPayment::getSalesmanNo).collect(Collectors.toList());
    }
}
